#include "gui/MainWindow.h"
#include "ui_MainWindow.h"
#include "QList"
#include <QPlastiqueStyle>
#include <QPalette>
#include <QFont>
#include "OSCthulhuClient.h"
#include <qabstractitemview.h>
#include <QDesktopWidget>

MainWindow::MainWindow(QWidget *parent ) :
    QMainWindow(parent),
    chatInput(this),
    flushButton(this),
    portList(this),
    listWidget(this),
    listWidget2(this),
    textEdit(this),
    chatLabel(this),
    usersLabel(this),
    portsLabel(this),
    objectsLabel(this),
    objectPrintWindow("Sync Object View", this),
    objectPrintPanel(this),
    objectPrintButton(this),
    objectPrinting(false),
    oscPrinting(false),
    oscPrintButton(this),
    oscPrintPanel(this),
    oscPrintWindow("OSC Packet Dump",this),
    connectionButton(this),
    optionsButton(this)
{
    setWindowTitle( "OSCthulhu Client" );
    setGeometry(100, 100, 400, 250);
    setFixedWidth(400);
    setFixedHeight(250);
    setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint | Qt::WindowMinimizeButtonHint);
    QFont cthulhuFont("Trebuchet MS", 11);
    cthulhuFont.setStyleHint(QFont::SansSerif);
    QFont cthulhuLabelFont("Trebuchet MS", 10);
    cthulhuLabelFont.setStyleHint(QFont::SansSerif);
    setFont(cthulhuFont);

    userName  = "N00b: ";
    QObject::connect( &chatInput, SIGNAL( returnPressed() ), this, SLOT( submitChatLine() ) );

    chatLabel.setGeometry(5, 5, 100, 15);
    chatLabel.setText("Chat");
    chatLabel.setFont(cthulhuLabelFont);

    textEdit.setGeometry(5, 25, (geometry().width()/2) - 5, geometry().height()-55);
    textEdit.setReadOnly( true );
    textEdit.setOverwriteMode( false );
    textEdit.setFont(cthulhuFont);
    textEdit.setFocusPolicy(Qt::NoFocus);

    chatInput.setGeometry(5, (geometry().height()-20) - 5, (geometry().width()/2) - 5, 20);
    chatInput.setFont(cthulhuFont);
    chatInput.setAttribute(Qt::WA_MacShowFocusRect, 0);

    connectionButton.setGeometry(geometry().width()/2 +5,3,100,20);
    connectionButton.setText("Disconnected");
    connectionButton.setStyleSheet("* { background-color: rgba(255,50,50,150) }");

    usersLabel.setGeometry(geometry().width() - 30, 5, 100, 15);
    usersLabel.setText("Users");
    usersLabel.setFont(cthulhuLabelFont);

    listWidget.setGeometry(geometry().width()/2 + 5, 25,
                           geometry().width()/2 - 10, (geometry().height() * 0.4) - 35);
    listWidget.setFont(cthulhuFont);
    listWidget.setFocusPolicy(Qt::NoFocus);

    portsLabel.setGeometry(geometry().width() - 30, (geometry().height() * 0.4) - 7, 100, 15);
    portsLabel.setText("Ports");
    portsLabel.setFont(cthulhuLabelFont);

    portList.setGeometry(geometry().width()/2 + 5, (geometry().height() * 0.4) + 10,
                         geometry().width()/2 - 10 , (geometry().height() * 0.1) + 5);
    portList.setFont(cthulhuFont);
    portList.setFocusPolicy(Qt::NoFocus);

    objectsLabel.setGeometry(geometry().width() - 40, (geometry().height() * 0.5) + 19, 100, 15);
    objectsLabel.setText("Objects");
    objectsLabel.setFont(cthulhuLabelFont);

    listWidget2.setGeometry(geometry().width()/2 + 5, (geometry().height() * 0.5) + 35,
                            geometry().width()/2 - 10, (geometry().height() * 0.4) - 35);
    listWidget2.setFont(cthulhuFont);
    listWidget2.setFocusPolicy(Qt::NoFocus);

    flushButton.setGeometry(geometry().width() - 51, geometry().height() - 22,
                            46, 17);
    flushButton.setText("flush");
    flushButton.setFont(cthulhuLabelFont);
    //QObject::connect(&flushButton, SIGNAL(clicked()), this, SLOT(flushSig()));
    //QObject::connect(&flushButton, SIGNAL(pressed()), this, SIGNAL(flush()));

    objectPrintButton.setGeometry(geometry().width()/2 + 5, geometry().height() - 22,
                            75, 17);
    objectPrintButton.setText("object window");
    objectPrintButton.setFont(cthulhuLabelFont);
    objectPrintButton.setCheckable(true);

    QObject::connect(&objectPrintButton, SIGNAL(clicked()), this, SLOT(openObjectPrintWindow()));
    QObject::connect(&objectPrintWindow, SIGNAL(visibilityChanged(bool)), this, SIGNAL(setObjectPrint(bool)));

    oscPrintButton.setGeometry(geometry().width()/2 + 85, geometry().height() - 22,
                            60, 17);

    oscPrintButton.setText("osc window");
    oscPrintButton.setFont(cthulhuLabelFont);
    oscPrintButton.setCheckable(true);

    QObject::connect(&oscPrintButton, SIGNAL(clicked()), this, SLOT(openOSCPrintWindow()));
    QObject::connect(&oscPrintWindow, SIGNAL(visibilityChanged(bool)), this, SIGNAL(setOSCPrint(bool)));

    objectPrintWindow.setGeometry(100, 100, 400, 250);
    objectPrintWindow.setFixedWidth(400);
    objectPrintWindow.setFixedHeight(250);
    objectPrintWindow.setAttribute(Qt::WA_MacAlwaysShowToolWindow);
    objectPrintWindow.setWindowFlags(Qt::WindowStaysOnTopHint);
    objectPrintPanel.setGeometry(0, 0, 400, 250);
    objectPrintPanel.setFont(cthulhuFont);
    objectPrintWindow.setWidget(&objectPrintPanel);
    objectPrintWindow.setFloating(true);
    objectPrintWindow.close();


    oscPrintPanel.setReadOnly( true );
    oscPrintPanel.setOverwriteMode( false );
    oscPrintPanel.setFont(cthulhuFont);
    oscPrintWindow.setGeometry(100, 100, 400, 250);
    oscPrintWindow.setFixedWidth(400);
    oscPrintWindow.setFixedHeight(250);
    oscPrintWindow.setAttribute(Qt::WA_MacAlwaysShowToolWindow);
    oscPrintWindow.setWindowFlags(Qt::WindowStaysOnTopHint);
    oscPrintPanel.setGeometry(0, 0, 400, 250);
    oscPrintPanel.setFont(cthulhuFont);
    oscPrintWindow.setWidget(&oscPrintPanel);
    oscPrintWindow.setFloating(true);
    oscPrintWindow.close();

    optionsButton.setGeometry(100,3,100,20);
    optionsButton.setText("Preferences");
    QObject::connect(&optionsButton,SIGNAL(clicked()),this,SLOT(toggleOptionsWindow()));

    show();
}

void MainWindow::addPeer(QString userName) {
    QWriteLocker locker(&peerlock);
    listWidget.insertItem(0,userName.append(QString(" [ ]")));
}

void MainWindow::changeUserPiece(QString userName, QString piece)
{
    QWriteLocker locker(&peerlock);
    QList<QListWidgetItem*> list = listWidget.findItems(userName,Qt::MatchContains);
    for (int i = 0; i < list.size(); ++i) {
        list.at(i)->setText(userName.append(QString(" [").append(piece).append("]")));
    };
}

void MainWindow::removePeer(QString userName) {
    QWriteLocker locker(&peerlock);
    QList<QListWidgetItem*> list = listWidget.findItems(userName,Qt::MatchContains);
    for (int i = 0; i < list.size(); ++i) {
        delete list.at(i);
    };
}

void MainWindow::addSyncObject(QString name) {
    QWriteLocker locker(&objectLock);
    listWidget2.insertItem(0,name);
}
void MainWindow::addSyncArg(QString name, int argNum, QVariant argValue) {

}
void MainWindow::setSyncArg(QString name, int argNum, QVariant argValue) {

}
void MainWindow::removeSyncObject(QString name,QString type,QString subtype) {
    QWriteLocker locker(&objectLock);
    QList<QListWidgetItem*> list = listWidget2.findItems(name,Qt::MatchCaseSensitive);
    for (int i = 0; i < list.size(); ++i) {
        delete list.at(i);
    };
}

/* add line to chat conversation */
void MainWindow::addChatLine( QString line ) {
    textEdit.moveCursor( QTextCursor::End, QTextCursor::MoveAnchor );
    textEdit.insertPlainText( line+"\n" );
    textEdit.ensureCursorVisible();
}

/* slot used for submitting chat lines */
void MainWindow::submitChatLine() {
    QString line = userName + chatInput.text();
    addChatLine( line );
    /* here we send the text across the network */
    client->sendChat( line );

    /* finally we clear the ChatInput */
    chatInput.clear();
}

QString MainWindow::getChatText()
{
    return textEdit.toPlainText();
}

/* Set our user name so we don't have to query every time we send text */
void MainWindow::setUserName( QString uN ) {
    userName = uN + ": ";
}

/* Give ourself a pointer to the client so we can network */
void MainWindow::setClient( OSCthulhuClient* c ) {
    client = c;
}

void MainWindow::addPort(int portNumber)
{
    portList.addItem(QString::number(portNumber));
}

void MainWindow::resetPortList()
{
    portList.clear();
}

void MainWindow::openObjectPrintWindow()
{
    if(!objectPrinting)
    {
        objectPrintWindow.move(geometry().x(), geometry().y()+251);
        objectPrintWindow.show();
        objectPrinting = true;
    }

    else
    {
        objectPrintWindow.close();
        objectPrinting = false;
    }
}

void MainWindow::printObject(QString name, QStringList arguments)
{
    QReadLocker locker(&printObjectLock);
    QList<QListWidgetItem*> list = objectPrintPanel.findItems(name, Qt::MatchContains);

    QString objectString = name + ": [";
    for(int i = 0; i < arguments.size(); i++)
    {
        objectString.append(arguments.at(i));
        if(i != arguments.size()-1)
        {
            objectString.append(", ");
        }
    }
    objectString.append("]");

    if(list.size() == 0)
    {
        objectPrintPanel.addItem(objectString);
    }

    else
    {
        list.at(0)->setText(objectString);
    }
}

void MainWindow::removePrintObject(QString name)
{
    QWriteLocker locker(&printObjectLock);
    QList<QListWidgetItem*> list = objectPrintPanel.findItems(name, Qt::MatchContains);
    for (int i = 0; i < list.size(); ++i) {
        delete list.at(i);
    }
}

void MainWindow::printOSC(QString message)
{
    oscPrintPanel.moveCursor( QTextCursor::End, QTextCursor::MoveAnchor );
    oscPrintPanel.insertPlainText( message+"\n" );
    oscPrintPanel.ensureCursorVisible();
}

void MainWindow::openOSCPrintWindow()
{
    if(!oscPrinting)
    {
        oscPrintWindow.move(geometry().x()+401, geometry().y()-16);
        oscPrintWindow.show();
        oscPrinting = true;
    }

    else
    {
        oscPrintWindow.close();
        oscPrinting = false;
    }

}

QToolButton* MainWindow::getFlushButton()
{
    return &flushButton;
}

void MainWindow::flushSig()
{
    emit flush();
}

void MainWindow::disconnected()
{
    connectionButton.setText("Disconnected");
    connectionButton.setStyleSheet("* { background-color: rgba(255,50,50,150) }");
}

void MainWindow::connected()
{
    connectionButton.setText("Connected");
    connectionButton.setStyleSheet("* { background-color: rgba(200,200,200,140) }");
}

void MainWindow::toggleOptionsWindow()
{
    if(!preferencesWindow.data()) {
        preferencesWindow = new PreferencesWindow(this);
        QObject::connect(
                    preferencesWindow,
                    SIGNAL(apply(QString,QString,QString,QString,int,int,int)),
                    client,
                    SLOT(setPreferences(QString,QString,QString,QString,int,int,int))
                    );
        //QObject::connect(optionsWindow, SIGNAL(destroyed()), this, SLOT(toggleOptionsWindow()));
        //preferencesWindow->move((QApplication::desktop()->rect().width()/2) - (preferencesWindow->geometry().width()/2),
        //                    (QApplication::desktop()->rect().height()/2) - (preferencesWindow->geometry().height()/2));
        preferencesWindow->show();
    } else {
        preferencesWindow->show();
    }
}

